package com.nmgolden.lanxin;


import com.alibaba.fastjson.JSONObject;
import com.nmgolden.lanxin.model.*;
import org.apache.http.Header;

import java.io.File;
import java.util.List;
import java.util.Map;

/**
 * 蓝信服务
 *
 * @author siger
 * @date 2020/12/20 10:27 上午 Wechat:Z2013111158
 */

@SuppressWarnings("unused")
public interface LanxinService {

    String ID_TYPE_EMPLOY_ID = "employ_id";
    String ID_TYPE_MOBILE = "mobile";
    String ID_TYPE_MAIL = "mail";
    String ID_TYPE_LOGIN = "login";
    String ID_TYPE_EXTERNAL_ID = "external_id";

    //***** token 相关接口 *****//

    /**
     * 获取url的签名相关数据
     *
     * @param url 需要签名（需要使用蓝信开放能力的页面）url
     * @return 签名包
     */
    SignaturePackage getSignaturePackage(String url);


    //***** 人员相关 *****//

    /**
     * 创建人员
     */
    String createUser(CreateUserRequestBody requestBody);

    /**
     * 创建人员-批量
     */
    List<CreateUsersResponseItem> createUsers(List<CreateUserRequestBody> users);

    /**
     * 更新人员
     */
    void updateUser(UpdateUserRequestBody requestBody);

    /**
     * 更新用户
     *
     * @TODO 需要保证顺序调用蓝信保存接口
     */
    void updateUser(String staffId, Map<String, Object> data);

    /**
     * 更新人员-批量
     *
     * @param requestBody
     * @return
     */
    List<LanxinResponse> updateUsers(List<UpdateUserRequestBody> requestBody);


    /**
     * 删除人员
     *
     * @param staffId
     */
    void deleteUser(String staffId);

    /**
     * @param pageNum   页码
     * @param pageSize  分页大小
     * @param staffId   当前人员 id
     * @param keyword   搜索关键字
     * @param recursive 是否递归
     * @param sectorIds 搜索部门
     */
    SearchResult searchUser(Integer pageNum, Integer pageSize, String staffId, String keyword, Boolean recursive, List<String> sectorIds);

    /**
     * 获取用户
     *
     * @param staffId 用户（人员）id
     * @return 人员对象
     */
    User getUser(String staffId);

    /**
     * 获取详细用户信息
     *
     * @param staffId 用户（人员）id
     * @return 人员详情
     */
    UserDetail getUserDetail(String staffId);

    /**
     * 通过唯一 id 获取 staffId
     *
     * @param idType  employ_id：人员编号（一般是HR系统的人员唯一编号）；
     *                mobile：手机号, 对应id_value格式为xx-137xxxxxx, 示例：86-13723129089
     *                邮箱地址
     *                login：账密方式登录蓝信时的人员登录账户名
     *                external_id：人员数据源外部唯一ID
     * @param idValue id_type 对应的值：人员编号，手机号，邮箱地址，登录账户名(需要携带组织标识 使用@连接,例如：zzbs@zhangsan)，人员外部ID
     * @return staffId
     */
    String getStaffId(String idType, String idValue);

    /**
     * 获取多个用户
     *
     * @param staffIds 多个用户（人员）id，使用','分隔
     * @return 用户（人员）列表
     */
    List<User> getUsers(String staffIds);

    /**
     * 获取多个用户
     */
    List<User> getUsers(List<String> staffIds);

    /**
     * 获取带此标签的人员列表
     *
     * @param tagName 标签名称
     * @return 带此标签的用户（人员）对象列表
     */
    List<User> getUsersByTagName(String tagName);


    /**
     * 获取人员分支祖先列表
     *
     * @param staffId 人员 id
     */
    List<List<Department>> getDepartmentAncestors4User(String staffId);

    /**
     * 获取根分支id
     * orgId+'-0'
     * 如 orgId = 8335 则根分支 id 为  8335-0
     * 注意此根分支 id 只能用于向蓝信做请求时使用。
     *
     * @return 根分支 id
     */
    String getRootDepartmentId();

    /**
     * 获取组织 id
     *
     * @return 组织 id
     */
    String getOrgId();

    /**
     * 创建部门
     */
    String createDepartment(CreateDepartmentRequestBody requestBody);

    /**
     * 更新部门
     */
    void updateDepartment(String deptId, UpdateDepartmentRequestBody requestBody);

    /**
     * 删除分支
     *
     * @param deptId 部门 id
     */
    void deleteDepartment(String deptId);

    /**
     * 获取部门（分支）详情
     *
     * @param departmentId 部门（分支）id
     */
    Department getDepartment(String departmentId);

    /**
     * 获取多个部门（分支）的详情
     *
     * @param departmentIds "," 分隔的部门 id
     * @return 部门(分支)列表
     */
    List<Department> getDepartments(String departmentIds);

    /**
     * 获取某个部门的子部门, 只获取一层。
     *
     * @param departmentId 父分支ID，根分支使用 “xxxx-0”，例如：524288-0  前半段为appid前半段
     * @return 部门（分支）列表
     */
    List<Department> getSubDepartments(String departmentId);


    /**
     * 获取某个部门的所有子部门
     * 递归获取，不包含当前部门
     *
     * @param departmentId 父分支ID，根分支使用 “xxxx-0”，例如：524288-0  前半段为appid前半段
     * @return 子部门（分支）列表
     */
    List<Department> getAllSubDepartments(String departmentId);

    /**
     * 获取某部门下蓝信用户
     * 目前只返回当前分支下的成员，不含子分支的成员
     *
     * @param departmentId 部门（分支）id
     * @return 用户（人员）列表
     */
    List<User> getUsersInDepartment(String departmentId);

    /**
     * 获取分支下以及子分支下成员
     * 递归获取
     *
     * @param departmentId 部门 id
     * @return 包含当前部分（分支）以及子部门（分支）下的所有用户（人员）列表
     */
    List<User> getAllUsersInDepartment(String departmentId);


    /**
     * 添加成员到部门
     *
     * @param deptId  部门 id
     * @param staffId 人员 id
     */
    void addMember2Department(String deptId, String staffId);

    /**
     * 从部门中国呢移除人员
     *
     * @param deptId  部门 id
     * @param staffId 人员 id
     */
    void removeMemberFromDepartment(String deptId, String staffId);

    /**
     * 移动部门
     *
     * @param deptId      部门 id
     * @param newParentId 目标父部门 id
     */
    void moveDepartment(String deptId, String newParentId);


    /********************* 消息类 *********************/
    /**
     * 发送应用卡片消息
     *
     * @param userIds            人员列表
     * @param appCardMsgDataInfo 消息内容
     * @return
     */
    MsgResponseData sendAppCardMessage(List<String> userIds, AppCardMsgDataInfo appCardMsgDataInfo);

    /**
     * 更新动态应用卡片消息
     *
     * @param msgId       消息 id
     * @param msgDataInfo appCardUpdateMsg：更新内容
     */
    void updateDynamicAppCardMsg(String msgId, AppCardUpdateMsgDataInfo msgDataInfo);

    /**
     * 发送 oacard 类型通知
     * <a href="https://openapi.lanxin.cn/doc/#/server-api/message/message_body_type">...</a>
     *
     * @param userIds  多个用户（人员）id
     * @param title    卡片标题
     * @param subtitle 卡片副标题
     * @param fields   卡片内容键值对
     * @param linkUrl  卡片连接地址
     */
    MsgResponseData sendOaCardMessage(String userIds, String title, String
            subtitle, List<MsgDataField> fields, String linkUrl);

    /**
     * 发送文本类型通知
     *
     * @see #sendTextMessage(List, String)
     */
    MsgResponseData sendTextMessage(String userIds, String text);

    /**
     * 发送文本类型通知
     * <a href="https://openapi.lanxin.cn/doc/#/server-api/message/message_body_type">...</a>
     *
     * @param userIds 多个用户（人员）id
     * @param text    内容文本
     */
    MsgResponseData sendTextMessage(List<String> userIds, String text);

    /**
     * @see #sendLinkCardMessage(List, List, String, String, String, String, String, String)
     */
    MsgResponseData sendLinkCardMessage(String userIds, String departmentIds, String title, String
            description, String iconLink, String link, String fromName, String fromIconLink);

    /**
     * 发送 linkCard 类型的通知消息
     *
     * @param userIds       多个用户（人员） id
     * @param departmentIds 多个部门（分支） id
     * @param title         标题
     * @param description   描述
     * @param iconLink      图标
     * @param link          连接
     * @param fromName      来源
     * @param fromIconLink  来源连接
     */
    MsgResponseData sendLinkCardMessage(List<String> userIds, List<String> departmentIds, String
            title, String description, String iconLink, String link, String fromName, String fromIconLink);

    /**
     * 发送 linkCard 类型的通知消息
     *
     * @param userIds       多个用户（人员） id
     * @param departmentIds 多个部门（分支） id
     * @param title         标题
     * @param description   描述
     * @param iconLink      图标
     * @param link          连接
     * @param fromName      来源
     * @param fromIconLink  来源连接
     */
    MsgResponseData sendLinkCardMessage(List<String> userIds, List<String> departmentIds, String
            title, String description, String iconLink, String link, String pcLink, String fromName, String fromIconLink);

    /**
     * 发送应用通知消息
     *
     * @param senderId    发送者 id
     * @param receiverIds 接受者 id
     * @param outline     摘要
     * @param msgType     消息类型
     * @param data        消息体
     */
    void sendNotification(String senderId, List<String> receiverIds, String outline, String msgType, MsgData
            data);

    /**
     * 更新通知消息会话状态
     *
     * @param userId      通知会话所有者，通知的peerId就是通知应用的appId
     * @param unreadCount 会话未读数。注：noDisturb 和unreadCount为互斥项，只能同时出现一个
     */
    void updateNotificationStatus(String userId, Integer unreadCount);

    /**
     * @param userId    通知会话所有者，通知的peerId就是通知应用的appId
     * @param noDisturb 免打扰标识。"true":开启免打扰功能，"false":关闭免打扰功能。注：noDistrub和unreadCount为互斥项，只能同时出现一个
     */
    void updateNotificationStatus(String userId, Boolean noDisturb);


    JSONObject getNotificationStatus(String userId);

    /**
     * 撤回消息
     * <a href="https://developer.lanxin.cn/official/article?id=646eca933d4e4adb7039c0e1&module=back-end-api&article_id=646ed9de3d4e4adb7039c149">...</a>
     *
     * @param chatType            消息类型，字符串枚举：staff, group, notification, account, bot。
     *                            说明： staff-私聊消息；group-群聊消息（包含webhook机器人群消息和应用机器人群消息）；notification-应用通知消息；account-应用号消息；bot--机器人私聊消息。
     *                            必填。
     * @param senderId            私聊（staff），群聊（group）时必须要填 senderId (staffId)。webhook机器人和应用机器人撤回群消息时不填。
     * @param messageIds          消息ID列表，必填
     * @param revokeNotice        撤回消息时展示的系统消息内容
     * @param revokeNoticeMediaId 撤回消息时展示的撤回图标的id
     */
    void revokeMessage(String chatType, String senderId, String messageIds, String revokeNotice, String
            revokeNoticeMediaId);

    /**
     * 发送应用变更事件
     */
    SendEventNotificationSubStatusItem sendAppChangeEvent(String userId, Boolean hasNew, Integer unreadNum);

    SendEventNotificationSubStatusItem sendAppChangeEvent(String userId, Boolean hasNew, Integer unreadNum, String entryId);


    /**
     * @see #sendMsgByBot(String, String, MsgDataInfo)
     */
    BotMsgResponseData sendMsgByBot(String url, MsgData msgData);

    /**
     * @see #sendMsgByBot(String, String, MsgDataInfo)
     */
    BotMsgResponseData sendMsgByBot(String url, MsgDataInfo msgDataInfo);

    /**
     * 使用机器人发送群消息
     * <a href="https://developer.lanxin.cn/official/article?id=646eca933d4e4adb7039c0e1&module=back-end-api&article_id=646eda463d4e4adb7039c150">...</a>
     *
     * @param url         发送url
     * @param secret      加签密钥
     * @param msgDataInfo 消息体详情
     */
    BotMsgResponseData sendMsgByBot(String url, String secret, MsgDataInfo msgDataInfo);

    /**
     * 登录蓝信
     * 使用免登陆授权码换取 staffId
     *
     * @param code 免授权登录码
     * @return staffId（用户 id）
     * @deprecated 请使用 getStaffIdByCode
     */
    @Deprecated
    String login(String code);

    /**
     * 使用免登陆授权码换取 staffId
     *
     * @param code 免授权登录码
     * @return staffId（用户 id）
     */
    String getStaffIdByCode(String code);

    /**
     * 通过二维码获取人员id
     */
    String getStaffIdByQrcode(String qrcode);

    /**
     * 获取完整的授权登录地址
     *
     * @param state       应用状态
     * @param redirectUrl 授权成功后重定向地址
     * @return 蓝信授权登录 url，可在浏览器中访问，蓝信登录成功后自动携带免授权登录码跳转到 redirectUrl
     */
    String getCompleteAuthUrl(String state, String redirectUrl);

    /**
     * 获取运营者列表
     */
    List<User> getOperators();

    /**
     * 获取拓展字段
     */
    List<ExtraField> getExtraFields();

    /**
     * 上传媒体文件
     *
     * @param file 文件
     * @param type 文件类型【VIDEO:1,IMAGE:2,AUDIO:3】
     */
    Map<String, String> uploadMedia(File file, String type);

    /**
     * 下载媒体文件
     *
     * @param mediaId  媒体 id
     * @param location 目标地址
     */
    void downloadMedia(String mediaId, String location);

    /**
     * 获取媒体文件
     */
    Media getMedia(String mediaId);

    /**
     * 根据文件分享ID下载文件
     *
     * @param shareId 媒体文件分享ID
     * @param path    下载目标地址
     */
    void downloadFileByShareId(String shareId, String path);

    /**
     * 获取通过文件分享 id 下载链接的响应头
     */
    List<Header> getHeadersByShareId(String shareId);

    LanxinAppConfig getConfig();
}
